II/ Khám phá dữ liệu
1. Dữ liệu có bao nhiêu dòng và bao nhiêu cột?
2. Mỗi dòng có ý nghĩa gì? Có vấn đề các dòng có ý nghĩa khác nhau không?
3. Dữ liệu có các dòng bị lặp không?
4. Mỗi cột có ý nghĩa gì?
5. Mỗi cột hiện đang có kiểu dữ liệu gì? Có cột nào có kiểu dữ liệu chưa phù hợp để có thể xử lý tiếp không?
6. Phân loại dạng kiểu dữ liệu
III/ Đưa ra câu hỏi có ý nghĩa cần trả lời
IV/ Trực quan để trả lời câu hỏi
V/ Nhìn lại
19127132 Trần Quang Duy
19127328 Đỗ Quốc Anh
! pip install plotly
! pip install seaborn
Requirement already satisfied: plotly in /home/katakuri_v/miniconda3/envs/min_ds-env/lib/python3.8/site-packages (5.4.0) Requirement already satisfied: tenacity>=6.2.0 in /home/katakuri_v/miniconda3/envs/min_ds-env/lib/python3.8/site-packages (from plotly) (8.0.1) Requirement already satisfied: six in /home/katakuri_v/miniconda3/envs/min_ds-env/lib/python3.8/site-packages (from plotly) (1.16.0) Requirement already satisfied: seaborn in /home/katakuri_v/miniconda3/envs/min_ds-env/lib/python3.8/site-packages (0.11.1) Requirement already satisfied: matplotlib>=2.2 in /home/katakuri_v/miniconda3/envs/min_ds-env/lib/python3.8/site-packages (from seaborn) (3.4.1) Requirement already satisfied: numpy>=1.15 in /home/katakuri_v/miniconda3/envs/min_ds-env/lib/python3.8/site-packages (from seaborn) (1.20.2) Requirement already satisfied: pandas>=0.23 in /home/katakuri_v/miniconda3/envs/min_ds-env/lib/python3.8/site-packages (from seaborn) (1.2.4) Requirement already satisfied: scipy>=1.0 in /home/katakuri_v/miniconda3/envs/min_ds-env/lib/python3.8/site-packages (from seaborn) (1.7.1) Requirement already satisfied: pyparsing>=2.2.1 in /home/katakuri_v/miniconda3/envs/min_ds-env/lib/python3.8/site-packages (from matplotlib>=2.2->seaborn) (2.4.7) Requirement already satisfied: kiwisolver>=1.0.1 in /home/katakuri_v/miniconda3/envs/min_ds-env/lib/python3.8/site-packages (from matplotlib>=2.2->seaborn) (1.3.2) Requirement already satisfied: python-dateutil>=2.7 in /home/katakuri_v/miniconda3/envs/min_ds-env/lib/python3.8/site-packages (from matplotlib>=2.2->seaborn) (2.8.2) Requirement already satisfied: cycler>=0.10 in /home/katakuri_v/miniconda3/envs/min_ds-env/lib/python3.8/site-packages (from matplotlib>=2.2->seaborn) (0.10.0) Requirement already satisfied: pillow>=6.2.0 in /home/katakuri_v/miniconda3/envs/min_ds-env/lib/python3.8/site-packages (from matplotlib>=2.2->seaborn) (8.3.2) Requirement already satisfied: pytz>=2017.3 in /home/katakuri_v/miniconda3/envs/min_ds-env/lib/python3.8/site-packages (from pandas>=0.23->seaborn) (2021.3) Requirement already satisfied: six in /home/katakuri_v/miniconda3/envs/min_ds-env/lib/python3.8/site-packages (from cycler>=0.10->matplotlib>=2.2->seaborn) (1.16.0)
import numpy as np
import pandas as pd # Dùng để đọc và hiển thị file csv/tsv
import matplotlib.pyplot as plt
import plotly
import plotly.express as px
import plotly.graph_objects as go
import seaborn as sns
from plotly.subplots import make_subplots
import math
import warnings
warnings.filterwarnings("ignore")
Trong đồ án này, nhóm em thu thập dữ liệu tập vgsale.csv từ kaggle
Link url: https://www.kaggle.com/mehulhyd/vgsales
Tập dữ liệu tên là "Video game sales" của tác giả unknown up lại từ nguồn khác nói về doanh thu bán ra của các game trong thập kỷ gần đây.
game_df = pd.read_csv('vgsales.csv')
game_df.head()
| Rank | Name | Platform | Year | Genre | Publisher | NA_Sales | EU_Sales | JP_Sales | Other_Sales | Global_Sales | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | Wii Sports | Wii | 2006.0 | Sports | Nintendo | 41.49 | 29.02 | 3.77 | 8.46 | 82.74 |
| 1 | 2 | Super Mario Bros. | NES | 1985.0 | Platform | Nintendo | 29.08 | 3.58 | 6.81 | 0.77 | 40.24 |
| 2 | 3 | Mario Kart Wii | Wii | 2008.0 | Racing | Nintendo | 15.85 | 12.88 | 3.79 | 3.31 | 35.82 |
| 3 | 4 | Wii Sports Resort | Wii | 2009.0 | Sports | Nintendo | 15.75 | 11.01 | 3.28 | 2.96 | 33.00 |
| 4 | 5 | Pokemon Red/Pokemon Blue | GB | 1996.0 | Role-Playing | Nintendo | 11.27 | 8.89 | 10.22 | 1.00 | 31.37 |
game_df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 16598 entries, 0 to 16597 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Rank 16598 non-null int64 1 Name 16598 non-null object 2 Platform 16598 non-null object 3 Year 16327 non-null float64 4 Genre 16598 non-null object 5 Publisher 16540 non-null object 6 NA_Sales 16598 non-null float64 7 EU_Sales 16598 non-null float64 8 JP_Sales 16598 non-null float64 9 Other_Sales 16598 non-null float64 10 Global_Sales 16598 non-null float64 dtypes: float64(6), int64(1), object(4) memory usage: 1.4+ MB
num_rows = len(game_df.index)
num_cols = len(game_df.columns)
print('Rows: ', num_rows, '- Cols: ', num_cols)
Rows: 16598 - Cols: 11
Quan sát sơ bộ dữ liệu ta thấy mỗi dòng chứa thông tin của một game được sắp xếp theo hạng doanh thu, và có vẻ không có vấn đề các dòng có ý nghĩa khác nhau.
game_df.index.duplicated().sum()
0
Mô tả ý nghĩa về các cột trong file "vgsale.csv":
col_dtypes = pd.Series(game_df.dtypes.values, index=game_df.dtypes.axes)
col_dtypes
Rank int64 Name object Platform object Year float64 Genre object Publisher object NA_Sales float64 EU_Sales float64 JP_Sales float64 Other_Sales float64 Global_Sales float64 dtype: object
def open_object_dtype(s, name):
dtypes = set()
# YOUR CODE HERE
#raise NotImplementedError()
if s.dtype == object:
dtypes = s.apply(lambda x: type(x))
print(name + ': ', set(dtypes))
open_object_dtype(game_df['Name'], 'Name')
open_object_dtype(game_df['Genre'], 'Genre')
open_object_dtype(game_df['Publisher'], 'Publisher')
Name: {<class 'str'>}
Genre: {<class 'str'>}
Publisher: {<class 'str'>, <class 'float'>}
Như vậy các cột object đa số đều là chuỗi và đều hợp với lại chức năng của nó chỉ riêng cột publisher có kèm số float vào vậy điều đầu tiên nghĩ tới là rất có thể cột này bị thiếu giá trị dữ liệu
game_df.isna().sum()
Rank 0 Name 0 Platform 0 Year 271 Genre 0 Publisher 58 NA_Sales 0 EU_Sales 0 JP_Sales 0 Other_Sales 0 Global_Sales 0 dtype: int64
Quả đúng như vậy và kèm theo ở trên thì các vấn đề cần tiền xử lý đó là:
+ Bổ sung các giá trị còn thiếu.
+ Đổi kiểu cột year sang int
Đối với việc xử lý giá trị thiếu thì:
+ Cột Year: dựa theo cột Platform thay năm xuất hiện nhiều nhất đối với platform đó
+ Cột Publisher: dựa theo cột Genre để điền
Tiền xử lý dữ liệu
def fill_missing(key1, key2):
missing_df = game_df[game_df[key1].isna()]
missing = list(set(game_df[game_df[key1].isna()][key2]))
temp = game_df[[key1, key2]].dropna().value_counts().reset_index().rename(columns={0 : 'Counts'})
filling = list()
for p in missing:
filling.append(temp[temp[key2] == p].reset_index()[key1][0])
for i in range(len(missing)):
missing_df.loc[missing_df[key2] == missing[i], key1] = filling[i]
game_df.loc[missing_df.index] = missing_df.loc[missing_df.index]
fill_missing('Publisher', 'Genre')
fill_missing('Year', 'Platform')
game_df['Year'] = game_df['Year'].astype(int)
game_df.head()
| Rank | Name | Platform | Year | Genre | Publisher | NA_Sales | EU_Sales | JP_Sales | Other_Sales | Global_Sales | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | Wii Sports | Wii | 2006 | Sports | Nintendo | 41.49 | 29.02 | 3.77 | 8.46 | 82.74 |
| 1 | 2 | Super Mario Bros. | NES | 1985 | Platform | Nintendo | 29.08 | 3.58 | 6.81 | 0.77 | 40.24 |
| 2 | 3 | Mario Kart Wii | Wii | 2008 | Racing | Nintendo | 15.85 | 12.88 | 3.79 | 3.31 | 35.82 |
| 3 | 4 | Wii Sports Resort | Wii | 2009 | Sports | Nintendo | 15.75 | 11.01 | 3.28 | 2.96 | 33.00 |
| 4 | 5 | Pokemon Red/Pokemon Blue | GB | 1996 | Role-Playing | Nintendo | 11.27 | 8.89 | 10.22 | 1.00 | 31.37 |
game_df.nunique()
Rank 16598 Name 11493 Platform 31 Year 39 Genre 12 Publisher 578 NA_Sales 409 EU_Sales 305 JP_Sales 244 Other_Sales 157 Global_Sales 623 dtype: int64
game_df.describe().T
| count | mean | std | min | 25% | 50% | 75% | max | |
|---|---|---|---|---|---|---|---|---|
| Rank | 16598.0 | 8300.605254 | 4791.853933 | 1.00 | 4151.25 | 8300.50 | 12449.75 | 16600.00 |
| Year | 16598.0 | 2006.386071 | 5.859628 | 1980.00 | 2003.00 | 2007.00 | 2010.00 | 2020.00 |
| NA_Sales | 16598.0 | 0.264667 | 0.816683 | 0.00 | 0.00 | 0.08 | 0.24 | 41.49 |
| EU_Sales | 16598.0 | 0.146652 | 0.505351 | 0.00 | 0.00 | 0.02 | 0.11 | 29.02 |
| JP_Sales | 16598.0 | 0.077782 | 0.309291 | 0.00 | 0.00 | 0.00 | 0.04 | 10.22 |
| Other_Sales | 16598.0 | 0.048063 | 0.188588 | 0.00 | 0.00 | 0.01 | 0.04 | 10.57 |
| Global_Sales | 16598.0 | 0.537441 | 1.555028 | 0.01 | 0.06 | 0.17 | 0.47 | 82.74 |
Nhìn vào số lượng giá trị khác nhau và thống kê mô tả ở trên thì có thể dễ dàng nhận thấy được có 4 cột category là Name, Year, Genre và Publisher. Còn lại là numeric
nume_col = ['Rank', 'Year', 'NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales', 'Global_Sales']
nume_col_profiles_df = pd.DataFrame(columns=nume_col, index=['missing_ratio', 'min', 'max'])
nume_col_profiles_df.loc['missing_ratio'] = pd.to_numeric((len(game_df[nume_col]) - game_df[nume_col].count()) / len(game_df[nume_col]) * 100, downcast="float")
nume_col_profiles_df.loc['min'] = game_df[nume_col].min()
nume_col_profiles_df.loc['max'] = game_df[nume_col].max()
nume_col_profiles_df[nume_col[0:len(nume_col)]] = nume_col_profiles_df[nume_col[0:len(nume_col)]].apply(pd.to_numeric, errors='coerce')
nume_col_profiles_df
| Rank | Year | NA_Sales | EU_Sales | JP_Sales | Other_Sales | Global_Sales | |
|---|---|---|---|---|---|---|---|
| missing_ratio | 0.0 | 0.0 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 |
| min | 1.0 | 1980.0 | 0.00 | 0.00 | 0.00 | 0.00 | 0.01 |
| max | 16600.0 | 2020.0 | 41.49 | 29.02 | 10.22 | 10.57 | 82.74 |
def compute_percentile(data, p):
sorted_data = sorted(data)
i = max(math.ceil(p/100 * len(sorted_data)) - 1, 0)
return sorted_data[i]
def draw(c):
lower_quartile = compute_percentile(game_df[c], 25)
median = compute_percentile(game_df[c], 50)
upper_quartile = compute_percentile(game_df[c], 75)
hist = plt.hist(game_df[c], [0.2, 0.4, 0.6, 0.8, 1],
edgecolor='black', density=True)
plt.xlabel('Quantity')
plt.ylabel('Proportion per quantity')
plt.title('Histogram of ' + c)
plt.xticks(hist[1])
plt.axvline(lower_quartile,
color='red', linestyle='solid', linewidth=3,
label='lower quartile')
plt.axvline(median,
color='violet', linestyle='dashed', linewidth=3,
label='median')
plt.axvline(upper_quartile,
color='yellow', linestyle='dotted', linewidth=3,
label='upper quartile')
plt.legend();
draw('NA_Sales')
draw('EU_Sales')
draw('JP_Sales')
draw('Other_Sales')
draw('Global_Sales')
Nhìn sơ qua không có gì nổi bật khi xem xem nhau :-)
cate_col = ['Name', 'Year', 'Genre', 'Publisher']
cate_col_profiles_df = pd.DataFrame(columns=cate_col, index=['missing_ratio', 'num_diff_vals', 'diff_vals'])
cate_col_profiles_df.loc['missing_ratio'] = pd.to_numeric((len(game_df[cate_col]) - game_df[cate_col].count()) / len(game_df[cate_col]) * 100, downcast="float")
cate_col_profiles_df.loc['num_diff_vals'] = game_df[cate_col].apply(lambda x: x.value_counts().count())
cate_col_profiles_df.loc['diff_vals'] = game_df[cate_col].apply(lambda x: x.value_counts().index)
cate_col_profiles_df
| Name | Year | Genre | Publisher | |
|---|---|---|---|---|
| missing_ratio | 0.0 | 0.0 | 0.0 | 0.0 |
| num_diff_vals | 11493 | 39 | 12 | 578 |
| diff_vals | Index(['Need for Speed: Most Wanted', 'Madden ... | Int64Index([2009, 2008, 2010, 2011, 2007, 2006... | Index(['Action', 'Sports', 'Misc', 'Role-Playi... | Index(['Electronic Arts', 'Activision', 'Ubiso... |
Sau khi đã khám phá dữ liệu và hiểu hơn về dữ liệu, em chia ra các vấn đề theo thời gian để trực quan hóa:
Ý nghĩa: Giúp nhìn nhận tổng quát rõ lại những thành tựu đã đạt được trong quá khứ và xem xét hướng đi kế tiếp để phát triển trong tương lai gần khi hiểu rõ được xu hướng thay đổi như thế nào qua thời gian khi ngành công nghiệp này phát triển vào thời điểm chuyển giao 2 thế hệ
-Game lần đầu tiên xuất hiện vào năm 1952, nhưng game mới được mọi người thật sự biết đến vào năm 1970 với sự xuất hiện của máy cầm tay màn hình tinh thể lỏng
-Năm 1995 là bước ngoặc cho thấy sự bùng nổ và hứa hẹn của ngành công nghiệp này với sự ra đời của thế hệ playstation đầu tiên.
-Cho đến nay thì sự phát triển của nó luôn ổn định (dữ liệu từ năm 2015 trở đi chưa kịp cập nhật)
growth = game_df[["Year","NA_Sales","EU_Sales","JP_Sales","Other_Sales","Global_Sales"]].groupby("Year").sum()
fig = px.bar(x = growth.index,y = growth["Global_Sales"])
fig.update_layout(
title="Growth of game industry",
yaxis_title="Million",
xaxis_title="Year"
)
fig.show()
fig = px.bar(growth,x = growth.index,y = ["NA_Sales","EU_Sales","JP_Sales","Other_Sales"])
fig.update_layout(
yaxis_title="Million"
)
fig.show()
-Biểu đồ trên cho thấy Bắc Mĩ là nơi áp đảo hoàn toàn các khu vực khác về số lượng đĩa game được bán ra và vẫn luôn ổn định.
-Ngay sau đó là khu vực Châu Âu. Đặc biệt Nhật là 1 quốc gia nhưng cũng không hẵn tới nổi lại được chia 1 cột riêng như thế và số liệu lại chỉ có vẻ như yếu thế một chút xíu so với khu vức lớn.
-Vậy Bắc Mĩ là nơi tiềm năng nhất để ngành công nghiệp này phát triển
Trước khi vào câu hỏi chính, ta cùng xem đâu là 5 trò chơi được bán chạy nhất lịch sử
top5 = game_df.head(5)
fig = px.bar(x = top5["Name"],y = top5["Global_Sales"])
fig.update_layout(
title="Top 5 game with most sales in the world",
yaxis_title="Million",
xaxis_title="Game title"
)
fig.show()
Và thể loại của chúng:
top5[["Name","Genre"]]
| Name | Genre | |
|---|---|---|
| 0 | Wii Sports | Sports |
| 1 | Super Mario Bros. | Platform |
| 2 | Mario Kart Wii | Racing |
| 3 | Wii Sports Resort | Sports |
| 4 | Pokemon Red/Pokemon Blue | Role-Playing |
Những thể loại này đã từng rất phổ biến và nhiều người yêu thích. Vậy đến thời điểm hiện tại chúng đã lỗi thời hay chưa ?
Tiền xử lý dữ liệu:
Gom nhóm theo thể loại và tạo ra dataframe best_genre_overtime cho thấy thể loại được mọi người ưa chuộng nhất thay đổi thế nào theo từng năm. Trên tiêu chí có số lương doanh thu cao nhất.
t1 = game_df[["Year","Genre","Global_Sales"]].groupby(["Year","Genre"]).sum().unstack(0).idxmax()
t2 = game_df[["Year","Genre","Global_Sales"]].groupby(["Year","Genre"]).sum().groupby(["Year"]).max()
t1.reset_index(level = 0,inplace = True,drop = True)
t1.name="Genre"
t2.name="Sales"
best_genre_overtime = pd.concat([t1, t2], axis=1)
best_genre_overtime.head()
| Genre | Global_Sales | |
|---|---|---|
| Year | ||
| 1980 | Shooter | 7.07 |
| 1981 | Action | 17.79 |
| 1982 | Puzzle | 10.03 |
| 1983 | Platform | 6.93 |
| 1984 | Shooter | 31.10 |
sns.set(rc={'figure.figsize':(15,7)})
plt.scatter(best_genre_overtime["Genre"],best_genre_overtime.index,s = best_genre_overtime["Global_Sales"],c = "purple");
-Dựa vào biểu đồ trên ta dễ dàng thấy được Action là thể loại luôn được mọi người đánh giá cao. Với 15 năm liên tục (trừ năm 2006) từ năm 2000 đến năm 2016 là thể loại được yêu thích nhất
-Năm 2006 thể loại sport Dẫn đầu với game Wii sport đạt kỉ lục bán được 82 triệu bản trên toàn thế giới.
-Và tại sao simulation tại sao lại mất hút thì ta sẽ tìm hiểu trong các phần sau :-)
b_genres = best_genre_overtime["Genre"].unique()
games_db = game_df[game_df['Year'] < 2016][["Year","Genre","Name"]].groupby(["Year","Genre"]).size().unstack(1).fillna(0)
games_db[b_genres].plot(figsize = (15,7), marker='o')
plt.title("games debut over time");
-b_genre là Dataframe chứa số trò chơi được ra mắt của từng thể loại theo từng năm.
-Ta có thể thấy với xuất phát điểm thuận lợi thì thể loại hành động vẫn luôn nằm trong top những thể loại được yêu thích nhất. Mặc cho năm 2006 chứng kiến sự bùng nổ của Wii sport.
-Thể loại nhập vai cũng đang rất ổn định theo thời gian mặc dù không cao như Action và sport.
-Như vậy chúng ta cũng đã dần có câu trả lời. Hành động vẫn luôn là xu hướng chung sau đó tới giả lập và nhập vai. Trong khi thể thao đang dần mất đi ưu thế của mình vì đã hết chủ đề để khai thác(như cốt truyện hay lối chơi chẳng hạn).
plat_db = game_df[game_df['Year'] < 2016][["Year","Platform","Name"]].groupby(["Year","Platform"]).size().unstack(1).fillna(0)
top_plat = plat_db.sum(axis=0).sort_values(axis=0, ascending=False).head(10).index
plat_db[top_plat].plot(figsize = (15,7), marker="d")
plt.title("Top 10 popular platform");
-Tiếp đến ta sẽ tìm hiểu đến xu hướng về hệ máy mà người tiêu dùng thường hướng đến. Đồ thị trên là top 10 hệ máy phổ biến nhất với trục tung là số game được ra trên hệ máy đó.
-Nintendo DS là cỗ máy phổ biến nhất. Đây là cỗ máy chơi game cầm tay nên có ưu thế về kích thước và sự tiện lợi.
-Vào những năm 2000 máy chơi game gia đình luôn là lựa chọn phổ biến với những Super Mario Bros, Sonic, Contra, .... Và luôn có chỗ đứng cho đến tận bây giờ thời điểm mà PS5 vừa ra mắt.
sns.lmplot(x='Global_Sales', y='NA_Sales', data=game_df, fit_reg=True)
sns.lmplot(x='Global_Sales', y='EU_Sales', data=game_df, fit_reg=True)
sns.lmplot(x='Global_Sales', y='JP_Sales', data=game_df, fit_reg=True)
sns.lmplot(x='Global_Sales', y='Other_Sales', data=game_df, fit_reg=True)
<seaborn.axisgrid.FacetGrid at 0x7f477003a220>
Như các scatter plot ở trên giữa từng khu vực với thế giới thì mặc dù Nhật là cái nôi của ngành công nghiệp game và rất áp đảo doanh thu nhưng dường như chỉ là bùng nổ vào lúc đầu và dần dần bớt nhiệt theo thời gian, trong khi 2 khu vực NA và EU thì dù ít nhưng chất lượng tốt và có khả năng là đáp ứng với nhu cầu thực tế nên có đường tuyến tính. Còn các khu vực khác vẫn là 1 ẩn số khi vẫn chưa nói lên được điều gì
Nên ta sẽ thử liên hệ giữa các khu vực với nhau
sns.pairplot(growth.drop(columns='Global_Sales'))
<seaborn.axisgrid.PairGrid at 0x7f477008ed90>
Nhìn vào biểu đồ trên thì có thể thấy sự phát triển tuyến tính của 2 khu vực phương Tây có thể sẽ rất bùng nổ trong tương lai trong khi đem 2 khu vực này với Nhật thì lại là đường cong về Nhật thì có lẽ là sự chuyển giao dần từ cái nôi sang thị trường có mức độ ảnh hưởng và tiềm năng hơn
Như vậy genre hay platform ảnh hưởng đến mức độ doanh thu thì ta sẽ thử tìm hiểu sau đây để cho biết được thị trường hiện nay phát triển như thế nào
Đầu tiên sẽ là genre với tổng doanh thu từng khu vực
sum_genre = game_df[['Genre', 'NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales']].groupby('Genre').sum()
sum_genre
| NA_Sales | EU_Sales | JP_Sales | Other_Sales | |
|---|---|---|---|---|
| Genre | ||||
| Action | 877.83 | 525.00 | 159.95 | 187.38 |
| Adventure | 105.80 | 64.13 | 52.07 | 16.81 |
| Fighting | 223.59 | 101.32 | 87.35 | 36.68 |
| Misc | 410.24 | 215.98 | 107.76 | 75.32 |
| Platform | 447.05 | 201.63 | 130.77 | 51.59 |
| Puzzle | 123.78 | 50.78 | 57.31 | 12.55 |
| Racing | 359.42 | 238.39 | 56.69 | 77.27 |
| Role-Playing | 327.28 | 188.06 | 352.31 | 59.61 |
| Shooter | 582.60 | 313.27 | 38.28 | 102.69 |
| Simulation | 183.31 | 113.38 | 63.70 | 31.52 |
| Sports | 683.35 | 376.85 | 135.37 | 134.97 |
| Strategy | 68.70 | 45.34 | 49.46 | 11.36 |
fig = go.Figure()
for c in sum_genre.columns:
fig.add_trace(go.Scatterpolar(
r=sum_genre[c],
theta=sum_genre.index,
fill='toself',
name=c
))
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
range=[0, int(sum_genre.max().max())]
)),
showlegend=True
)
fig.show()
Qua radar chart trên có thể thấy thằng NA đi đầu gần như mọi thể loại cho thấy sở thích của khu vực này khá là đa dạng và như đã nói ở đầu thì thông qua điều này càng chứng minh chắc chắn rằng nơi đây là thiên đường để phát triển game. Tiếp sau đó là EU cũng đa dạng như NA và đây là số liệu cũ nên có thể nói nơi đây là khu vực tiềm năng để phát triển như NA cho các start-up khởi nghiệp. Và đến Japan thì ta thấy khá hay ho khi chỉ có thể loại nhập vai đã gánh cả 1 khu vực như thế khi các thể loại còn ít hơn cả các khu vực khác và kết hợp với truyền thống văn hóa thực tế thì có thể nói rằng một phần đúng khi độ giáo dục cao của Nhật Bản đã phản ánh phần nào tới sở thích chơi game của người dân nước châu Á như thế này và trái ngược với văn hóa đa dạng của các nước phương Tây.
Như thế văn hóa phản ánh sở thích từ đó dẫn đến mức độ doanh thu khi đối với khu vực Nhật Bản phải đáp ứng chất lượng còn các khu vực kia là số lượng
Kế tiếp ta sẽ xét tới platform
sum_platform = pd.DataFrame()
for c in ['NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales', 'Global_Sales']:
df = game_df.groupby('Platform')[[c]].sum().sort_values(by=[c],ascending=[False]).reset_index()
df.rename(columns = {'Platform': 'Platform_' + c}, inplace = True)
sum_platform = pd.concat([sum_platform, df], axis=1)
sum_platform
| Platform_NA_Sales | NA_Sales | Platform_EU_Sales | EU_Sales | Platform_JP_Sales | JP_Sales | Platform_Other_Sales | Other_Sales | Platform_Global_Sales | Global_Sales | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | X360 | 601.05 | PS3 | 343.71 | DS | 175.57 | PS2 | 193.44 | PS2 | 1255.64 |
| 1 | PS2 | 583.84 | PS2 | 339.29 | PS | 139.82 | PS3 | 141.93 | X360 | 979.96 |
| 2 | Wii | 507.71 | X360 | 280.58 | PS2 | 139.20 | X360 | 85.54 | PS3 | 957.84 |
| 3 | PS3 | 392.26 | Wii | 268.38 | SNES | 116.55 | Wii | 80.61 | Wii | 926.71 |
| 4 | DS | 390.71 | PS | 213.60 | NES | 98.65 | DS | 60.53 | DS | 822.49 |
| 5 | PS | 336.51 | DS | 194.65 | 3DS | 97.35 | PS4 | 43.36 | PS | 730.66 |
| 6 | GBA | 187.54 | PC | 139.68 | GB | 85.12 | PSP | 42.19 | GBA | 318.50 |
| 7 | XB | 186.69 | PS4 | 123.70 | PS3 | 79.99 | PS | 40.91 | PSP | 296.28 |
| 8 | N64 | 139.02 | GBA | 75.25 | PSP | 76.79 | PC | 24.86 | PS4 | 278.10 |
| 9 | GC | 133.46 | PSP | 68.25 | Wii | 69.35 | 3DS | 12.63 | PC | 258.82 |
| 10 | NES | 125.94 | XB | 60.95 | GBA | 47.33 | XOne | 11.92 | XB | 258.26 |
| 11 | GB | 114.32 | 3DS | 58.52 | N64 | 34.22 | XB | 8.72 | GB | 255.45 |
| 12 | PSP | 108.99 | GB | 47.82 | SAT | 32.26 | PSV | 8.45 | NES | 251.07 |
| 13 | PS4 | 96.80 | XOne | 45.65 | GC | 21.58 | GB | 8.20 | 3DS | 247.46 |
| 14 | PC | 93.28 | N64 | 41.06 | PSV | 20.96 | GBA | 7.73 | N64 | 218.88 |
| 15 | 2600 | 90.60 | GC | 38.71 | PS4 | 14.30 | WiiU | 6.45 | SNES | 200.05 |
| 16 | XOne | 83.19 | WiiU | 24.23 | WiiU | 12.79 | NES | 5.31 | GC | 199.36 |
| 17 | 3DS | 78.87 | NES | 21.15 | X360 | 12.43 | GC | 5.18 | XOne | 141.06 |
| 18 | SNES | 61.23 | SNES | 19.04 | DC | 8.56 | N64 | 4.38 | 2600 | 97.08 |
| 19 | WiiU | 38.32 | PSV | 16.33 | GEN | 2.67 | SNES | 3.22 | WiiU | 81.86 |
| 20 | GEN | 19.27 | GEN | 5.52 | NG | 1.44 | 2600 | 0.91 | PSV | 61.93 |
| 21 | PSV | 16.20 | 2600 | 5.47 | WS | 1.42 | GEN | 0.89 | SAT | 33.59 |
| 22 | DC | 5.43 | DC | 1.69 | XB | 1.38 | DC | 0.27 | GEN | 28.36 |
| 23 | SCD | 1.00 | SAT | 0.54 | SCD | 0.45 | SAT | 0.07 | DC | 15.97 |
| 24 | SAT | 0.72 | SCD | 0.36 | XOne | 0.34 | SCD | 0.05 | SCD | 1.87 |
| 25 | 3DO | 0.00 | WS | 0.00 | PC | 0.17 | NG | 0.00 | NG | 1.44 |
| 26 | PCFX | 0.00 | TG16 | 0.00 | TG16 | 0.16 | TG16 | 0.00 | WS | 1.42 |
| 27 | NG | 0.00 | 3DO | 0.00 | 3DO | 0.10 | WS | 0.00 | TG16 | 0.16 |
| 28 | GG | 0.00 | GG | 0.00 | GG | 0.04 | GG | 0.00 | 3DO | 0.10 |
| 29 | TG16 | 0.00 | NG | 0.00 | PCFX | 0.03 | 3DO | 0.00 | GG | 0.04 |
| 30 | WS | 0.00 | PCFX | 0.00 | 2600 | 0.00 | PCFX | 0.00 | PCFX | 0.03 |
platform_plot = make_subplots(rows=5, cols=1, shared_yaxes=True,subplot_titles=('NA top platforms', 'EU top platforms', 'JP top platforms', 'Others top platforms', 'Global top platforms'))
i = 1
j = 1
for c in ['NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales', 'Global_Sales']:
platform_plot.add_trace(go.Bar(x=sum_platform['Platform_' + c], y=sum_platform[c], marker=dict(color=[i, i + 1, i + 2],coloraxis='coloraxis')), j, 1);
j = j + 1
platform_plot.update_layout(height=900,width=500, coloraxis=dict(colorscale='Magenta'), showlegend=False)
platform_plot.show()
Nhìn vào trên thì các dòng máy PS, DS thống lĩnh các thị trường bao gồm cả thế giới nhưng lại không thể chiếm được thị trường NA khi nơi đây là của dòng X360 và Wii. Hơn hết là dù dòng PS thống lĩnh nhưng trong khu vực Nhật Bản lại chịu xếp sau DS => vậy liệu có phải có nhà sản xuất PS có xu hướng phát triển thị trường nước ngoài hơn là trong nước khi theo thực tế thì hãng sản xuất PS là đến từ Nhật thì ta sẽ xét trong phần sau đây
sum_publisher = pd.DataFrame()
for c in ['NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales', 'Global_Sales']:
df = game_df.groupby('Publisher').sum().sort_values(by=[c],ascending=[False]).reset_index()[['Publisher', c]]
df = df.rename(columns={c:'Sales'})
df['Region'] = c
sum_publisher = pd.concat([sum_publisher, df.head(5)], axis=0)
sum_publisher = sum_publisher.reset_index().drop(columns='index').fillna(0)
sum_publisher
| Publisher | Sales | Region | |
|---|---|---|---|
| 0 | Nintendo | 816.87 | NA_Sales |
| 1 | Electronic Arts | 595.88 | NA_Sales |
| 2 | Activision | 430.00 | NA_Sales |
| 3 | Sony Computer Entertainment | 265.22 | NA_Sales |
| 4 | Ubisoft | 259.00 | NA_Sales |
| 5 | Nintendo | 419.25 | EU_Sales |
| 6 | Electronic Arts | 371.83 | EU_Sales |
| 7 | Activision | 215.64 | EU_Sales |
| 8 | Sony Computer Entertainment | 187.72 | EU_Sales |
| 9 | Ubisoft | 165.55 | EU_Sales |
| 10 | Nintendo | 455.42 | JP_Sales |
| 11 | Namco Bandai Games | 127.24 | JP_Sales |
| 12 | Konami Digital Entertainment | 91.30 | JP_Sales |
| 13 | Sony Computer Entertainment | 74.10 | JP_Sales |
| 14 | Capcom | 68.08 | JP_Sales |
| 15 | Electronic Arts | 129.87 | Other_Sales |
| 16 | Nintendo | 95.33 | Other_Sales |
| 17 | Sony Computer Entertainment | 80.45 | Other_Sales |
| 18 | Activision | 75.37 | Other_Sales |
| 19 | Take-Two Interactive | 55.24 | Other_Sales |
| 20 | Nintendo | 1787.07 | Global_Sales |
| 21 | Electronic Arts | 1111.91 | Global_Sales |
| 22 | Activision | 728.36 | Global_Sales |
| 23 | Sony Computer Entertainment | 607.50 | Global_Sales |
| 24 | Ubisoft | 482.77 | Global_Sales |
px.scatter(sum_publisher, x='Publisher', y='Sales', color='Region', size='Sales')
Có vẻ như nintendo đi đầu trong mọi khu vực và đã khác với những gì ta nghĩ rằng chỉ phát triển ở trong mỗi Nhật Bản và có vẻ nó là nguyên tố khiến cho ta thấy được đường cong ở biểu đồ mối liên hệ giữa Nhật với NA, nhưng liệu nó có thât sự là sẽ dẫn đầu hay chỉ đơn giản là vì nhà phát triển đầu tiên nên mọi người đều tò mò và muốn thử khi mà nhà phát triển này làm các con game có thể loại đã không còn phổ biến so với hiện giờ (phần tương lai sẽ thấy rõ điều này), và 1 nhà đồng hương khác là sony lại không chọn thị trường nội địa mà lại chọn sang nước ngoài khi mà ta thấy các hãng lớn khác cũng có doanh thu lớn ở các khu vực ngoài Nhật và cũng đã nói ở trên khi văn hóa Nhật khá kén khi họ chọn việc học làm gốc hơn là chơi game như những khu vực khác khi mà các nhà sản xuất nước ngoài biết đến phát triển game và tự chiếm lĩnh thị trường nội địa dẫn đến các nhà sản xuất khác của Nhật trừ nintendo đã không thể chen chân vào
game_df.head()
| Rank | Name | Platform | Year | Genre | Publisher | NA_Sales | EU_Sales | JP_Sales | Other_Sales | Global_Sales | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | Wii Sports | Wii | 2006 | Sports | Nintendo | 41.49 | 29.02 | 3.77 | 8.46 | 82.74 |
| 1 | 2 | Super Mario Bros. | NES | 1985 | Platform | Nintendo | 29.08 | 3.58 | 6.81 | 0.77 | 40.24 |
| 2 | 3 | Mario Kart Wii | Wii | 2008 | Racing | Nintendo | 15.85 | 12.88 | 3.79 | 3.31 | 35.82 |
| 3 | 4 | Wii Sports Resort | Wii | 2009 | Sports | Nintendo | 15.75 | 11.01 | 3.28 | 2.96 | 33.00 |
| 4 | 5 | Pokemon Red/Pokemon Blue | GB | 1996 | Role-Playing | Nintendo | 11.27 | 8.89 | 10.22 | 1.00 | 31.37 |
game_df[game_df['Year'] == 2015].head()
| Rank | Name | Platform | Year | Genre | Publisher | NA_Sales | EU_Sales | JP_Sales | Other_Sales | Global_Sales | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 33 | 34 | Call of Duty: Black Ops 3 | PS4 | 2015 | Shooter | Activision | 5.77 | 5.81 | 0.35 | 2.31 | 14.24 |
| 77 | 78 | FIFA 16 | PS4 | 2015 | Sports | Electronic Arts | 1.11 | 6.06 | 0.06 | 1.26 | 8.49 |
| 92 | 93 | Star Wars Battlefront (2015) | PS4 | 2015 | Shooter | Electronic Arts | 2.93 | 3.29 | 0.22 | 1.23 | 7.67 |
| 101 | 102 | Call of Duty: Black Ops 3 | XOne | 2015 | Shooter | Activision | 4.52 | 2.09 | 0.01 | 0.67 | 7.30 |
| 109 | 110 | Fallout 4 | PS4 | 2015 | Role-Playing | Bethesda Softworks | 2.47 | 3.15 | 0.24 | 1.10 | 6.96 |
Như lẽ tự nhiên các hệ máy mới ra dần trở nên phổ biến và các game dành cho nó cũng ra nhiều hơn vì vậy top 5 game 2015 đều chơi trên PS4 và XOne (đều 2013 ra mắt). Thể loại bắn súng có một bước chuyển mình mạnh mẽ mặc dù tổng doanh thu của nó không bằng hành động nhưng lại có những game tiêu biểu như Call Of Duty, Star Wars Battlefront, ... (lấy chất lượng bù số lượng)
latest_df = game_df[game_df['Year'] == 2016]
latest_df.head(10)
| Rank | Name | Platform | Year | Genre | Publisher | NA_Sales | EU_Sales | JP_Sales | Other_Sales | Global_Sales | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 221 | 222 | FIFA 17 | PS4 | 2016 | Sports | Electronic Arts | 0.28 | 3.75 | 0.06 | 0.69 | 4.77 |
| 271 | 272 | Uncharted 4: A Thief's End | PS4 | 2016 | Shooter | Sony Computer Entertainment | 1.30 | 2.07 | 0.18 | 0.65 | 4.20 |
| 351 | 352 | Tom Clancy's The Division | PS4 | 2016 | Shooter | Ubisoft | 1.28 | 1.61 | 0.15 | 0.57 | 3.61 |
| 770 | 772 | Far Cry: Primal | PS4 | 2016 | Action | Ubisoft | 0.59 | 1.16 | 0.06 | 0.33 | 2.13 |
| 845 | 847 | Tom Clancy's The Division | XOne | 2016 | Shooter | Ubisoft | 1.20 | 0.62 | 0.00 | 0.18 | 2.01 |
| 1026 | 1028 | Overwatch | PS4 | 2016 | Shooter | Activision | 0.64 | 0.68 | 0.14 | 0.26 | 1.73 |
| 1156 | 1158 | No Man's Sky | PS4 | 2016 | Action | Hello Games | 0.58 | 0.74 | 0.02 | 0.26 | 1.60 |
| 1189 | 1191 | Dark Souls III | PS4 | 2016 | Role-Playing | Namco Bandai Games | 0.58 | 0.44 | 0.33 | 0.21 | 1.56 |
| 1224 | 1226 | FIFA 17 | XOne | 2016 | Sports | Electronic Arts | 0.17 | 1.26 | 0.00 | 0.10 | 1.53 |
| 1389 | 1391 | Doom (2016) | PS4 | 2016 | Shooter | Bethesda Softworks | 0.49 | 0.66 | 0.02 | 0.22 | 1.39 |
Có vẻ như shooter đang dần được ưu chuộng khi mọi người bắt đầu muốn một cái gì đó mới mẻ hơn như game fps để đối kháng với nhau hơn là việc chỉ chơi với npc khá nhàm chán. Bên cạnh đó sport vẫn luôn ổn định khi mà thay vì ra ngoài chơi thì có thể thông qua game trong khi đó role play cũng có vẻ manh nha bùng dậy vào những năm nay và đúng như vậy khi hiện giờ 2021 1 game phổ biến toàn cầu cho thể loại này là GTA V hay LOL của Mỹ
Về hệ máy thì vẫn là sử dụng cái hệ máy mới
Về nhà sản xuất thì có thể thấy nintendo dần bị đào thải khi không đáp ứng được nhu cầu thực tế bằng chứng là các con game của họ chỉ đơn thuần là giải trí cao chứ không thỏa mãn được các yếu tố khác, còn sony thì có thể cho thấy hướng đầu tư ra thị trường nước ngoài là điều đúng đắn, còn như nhà độc quyền ubisoft của Mỹ thì vẫn luôn sát sao với thực tế
Như vậy có thể thấy hướng đi thực tế cho tương lai là cần đầu tư vào các hệ máy, thể loại thì phát triển đúng với nhu cầu thị trường cũng như nên phát triển các hậu bản cho các con game cưng đã nhận được nhiều sự ủng hộ trước đó thì là tất cả những gì ta đúc kết được cho tương lai gần
Duy
Trong quá trình làm bài, em thường gặp khó khắn trong việc tìm biểu đồ thích hợp để biểu diễn ý nghía mà mình muốn hướng tới. Ngoài ra việc code với groupby cũng gây cho em một chút khó khắn để lọc ra dataframe mình muốn.
Anh
Khó khăn về cách diễn giải biểu đồ, 1 chút rắc rối với tiền xử lý tạo dataframe để trực quan hóa
Học được nên vẽ biểu đồ sao cho hợp lý khi radar chart cho genre nhưng không dùng cho platform và publisher, nên tạo dataframe phù hợp để nhìn thấy thông tin muốn làm dễ hơn, biết sắp xếp thứ tự bố cục bài làm sao cho hợp lý
Nếu được thì em sẽ làm kỹ hơn phần nước đi tương lai và top game để cho thấy các hậu bản của con game top ảnh hưởng như thế nào tới sau này và cho 2 mục này liên hệ rắn chắc hơn bên cạnh đó cũng sẽ thu thập thêm dữ liệu cho những năm sau này để có cái nhìn thực tế hơn cho tình hình hiện nay thay vì dự đoán cái hiện giờ nó đang diễn ra
Các code đã có sẵn trong dataset của kaggle
Các cách vẽ trong các trang: